/*
 * @Description: 封装axios
 * @Author: liushuang
 * @Date: 2022-03-24 15:42:44
 * @LastEditTime: 2022-11-11 20:52:11
 */
import axios from 'axios'
import { ElMessage } from 'element-plus'
import { isEmptyObject, isType, debounce } from 'web-utils-super'
import store from '@/store'
import router from '@/router'
import { addPending, removePending } from './cancel'
import requestError from './error'

const service = axios.create({
  baseURL: import.meta.env.VITE_BASE_URL || '/',
  timeout: 30000
})

/**
 * @desc: 错误提示防抖
 * @param {*} debounce
 * @param {*} des
 */
const showError = debounce((message, des) => {
  ElMessage.error(message || des)
}, 150)

// headers: {
//   formdata: 'formdata' 接口这样设置post和put请求采用formdata方式，而不是payload
// },
// return request({
//   url: '...',
//   method: 'get',
//   data,
//   responseType: 'blob' 后端接口返回二进制数据 需添加这个属性
// })
service.interceptors.request.use(
  (config) => {
    if (
      config.headers?.formdata === 'formdata'
      && (config.method === 'post' || config.method === 'put')
    ) {
      config.transformRequest = [
        (data) => {
          let ret = ''
          if (isType(data) === 'object' && !isEmptyObject(data)) {
            Object.keys(data).forEach((item) => {
              ret += `${encodeURIComponent(item)}=${encodeURIComponent(
                data[item]
              )}&`
            })
          }
          return ret
        }
      ]
    }
    delete config.headers.payload
    // 将接口添加进待取消队列
    addPending(config)
    return config
  },
  (error) => {
    ElMessage.error(error)
    Promise.reject(error)
  }
)

service.interceptors.response.use(
  (response) => {
    const { config, data, status } = response
    const { code, message } = data
    removePending(config.url)
    if (status === 200 && (code === 200 || code === '000000')) {
      return data
    }
    // 二进制流
    if (config.responseType === 'blob' && data) {
      return data
    }
    const errMsg = `请求异常:${
      JSON.stringify({ url: config.url, code, message })
    }`
    showError(message, errMsg)
    return Promise.reject(errMsg)
  },
  (error) => {
    const err = error
    if (axios.isCancel(error)) {
      // 接口被取消 返回不同的标志 页面可做出相应的处理
      err.cancel = true
    } else {
      // 接口报错
      err.error = true
      err.des = error?.response?.data?.message || requestError(error)
      showError(err.des, '接口请求异常')
      const code = error?.response?.data?.code
      // 002005     token不存在
      // 002007     token不可使用
      // 002004     token失效
      if (code === '002005' || code === '002007' || code === '002004') {
        setTimeout(() => {
          store.dispatch('user/resetAll')
          router.push('/login')
        }, 1000)
      }
    }
    return Promise.reject(err)
  }
)

/**
 * @desc: 封装的请求函数 api文件里使用
 * @param {*} config
 */
const request = (config) => {
  let c = JSON.parse(JSON.stringify(config))
  if (c.this) {
    c = {
      ...c,
      ...c.this
    }
  }
  const method = c.method.toLowerCase()
  if (method === 'get' || method === 'delete') {
    c.params = c.data
  }
  return service(c)
}

export default request
